package com.example.service.impl;

import com.example.common.Result;
import com.example.dto.ChangePasswordDTO;
import com.example.dto.LoginDTO;
import com.example.dto.RegisterDTO;
import com.example.dto.UpdateProfileDTO;
import com.example.entity.Role;
import com.example.entity.User;
import com.example.entity.UserRole;
import com.example.exception.BusinessException;
import com.example.exception.AuthenticationException;
import com.example.exception.SystemException;
import com.example.exception.ErrorCode;
import com.example.mapper.RoleMapper;
import com.example.mapper.UserMapper;
import com.example.mapper.UserRoleMapper;
import com.example.service.CaptchaService;
import com.example.service.EmailVerificationService;
import com.example.service.MenuService;
import com.example.service.OnlineUserService;
import com.example.service.PermissionInitService;
import com.example.service.PhoneVerificationService;
import com.example.service.UserService;
import com.example.util.IpUtil;
import com.example.util.JwtUtil;
import com.example.util.UserContextUtil;
import com.example.vo.LoginVO;
import com.example.vo.OnlineUserVO;
import com.example.vo.TokenRefreshVO;
import com.example.vo.UserInfoVO;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import com.example.util.PasswordUtil;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserServiceImpl implements UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private RoleMapper roleMapper;
    
    @Autowired
    private UserRoleMapper userRoleMapper;
    
    @Autowired
    private JwtUtil jwtUtil;
    
    @Autowired
    private MenuService menuService;

    @Autowired
    private PermissionInitService permissionInitService;
    

    
    @Autowired
    private PasswordUtil passwordUtil;
    
    @Autowired
    private UserContextUtil userContextUtil;

    @Autowired
    private OnlineUserService onlineUserService;

    @Autowired
    private CaptchaService captchaService;

    @Autowired
    private PhoneVerificationService phoneVerificationService;

    @Autowired
    private EmailVerificationService emailVerificationService;

    @Override
    public LoginVO login(LoginDTO loginDTO) {
        User user = null;
        String loginType = loginDTO.getLoginType();

        if (loginType == null || "password".equals(loginType)) {
            // 用户名密码登录 - 需要验证图形验证码
            if (captchaService.isCaptchaRequired("login")) {
                if (loginDTO.getCaptchaId() == null || loginDTO.getCaptchaCode() == null) {
                    throw AuthenticationException.captchaError();
                }

                Result<Void> captchaResult = captchaService.verifyCaptcha(loginDTO.getCaptchaId(), loginDTO.getCaptchaCode());
                if (!captchaResult.isSuccess()) {
                    throw AuthenticationException.captchaError();
                }
            }

            user = loginWithPassword(loginDTO);
        } else if ("phone".equals(loginType)) {
            // 手机号验证码登录
            user = loginWithPhone(loginDTO);
        } else if ("email".equals(loginType)) {
            // 邮箱验证码登录
            user = loginWithEmail(loginDTO);
        } else {
            throw AuthenticationException.loginFailed("不支持的登录方式");
        }

        if (user.getStatus() == 0) {
            throw BusinessException.userDisabled();
        }

        // 生成访问token和刷新token
        String accessToken = jwtUtil.generateToken(user.getUsername());
        String refreshToken = jwtUtil.generateRefreshToken(user.getUsername());

        // 获取用户信息
        UserInfoVO userInfo = getUserInfo(user.getUsername());

        // 记录用户上线
        recordUserOnline(accessToken, user);

        LoginVO loginVO = new LoginVO();
        loginVO.setToken(accessToken);
        loginVO.setRefreshToken(refreshToken);
        loginVO.setUserInfo(userInfo);

        return loginVO;
    }
    
    @Override
    public void register(RegisterDTO registerDTO) {
        String registerType = registerDTO.getRegisterType();

        // 验证注册方式
        if ("phone".equals(registerType)) {
            // 手机号验证码注册
            if (registerDTO.getPhone() == null || registerDTO.getPhoneCode() == null) {
                throw new BusinessException(ErrorCode.PARAMETER_ERROR, "手机号和验证码不能为空");
            }

            // 验证手机验证码
            Result<Void> verifyResult = phoneVerificationService.verifyRegisterCode(registerDTO.getPhone(), registerDTO.getPhoneCode());
            if (!verifyResult.isSuccess()) {
                throw new BusinessException(ErrorCode.AUTH_VERIFICATION_CODE_ERROR, verifyResult.getMessage());
            }

        } else if ("email".equals(registerType)) {
            // 邮箱验证码注册
            if (registerDTO.getEmail() == null || registerDTO.getEmailCode() == null) {
                throw new BusinessException(ErrorCode.PARAMETER_ERROR, "邮箱和验证码不能为空");
            }

            // 验证邮箱验证码
            Result<Void> verifyResult = emailVerificationService.verifyRegisterCode(registerDTO.getEmail(), registerDTO.getEmailCode());
            if (!verifyResult.isSuccess()) {
                throw new BusinessException(ErrorCode.AUTH_VERIFICATION_CODE_ERROR, verifyResult.getMessage());
            }
        }

        // 检查用户名是否存在
        if (registerDTO.getUsername() != null) {
            User existUser = userMapper.selectByUsername(registerDTO.getUsername());
            if (existUser != null) {
                throw BusinessException.userAlreadyExists(registerDTO.getUsername());
            }
        }

//        // 检查邮箱是否已注册
//        if (registerDTO.getEmail() != null) {
//            User existUser = userMapper.selectByEmail(registerDTO.getEmail());
//            if (existUser != null) {
//                throw new RuntimeException("该邮箱已注册");
//            }
//        }
//
//        // 检查手机号是否已注册
//        if (registerDTO.getPhone() != null) {
//            User existUser = userMapper.selectByPhone(registerDTO.getPhone());
//            if (existUser != null) {
//                throw new RuntimeException("该手机号已注册");
//            }
//        }

        // 创建用户
        User user = new User();
        user.setUsername(registerDTO.getUsername());
        if (registerDTO.getPassword() != null) {
            user.setPassword(passwordUtil.encode(registerDTO.getPassword()));
        } else {
            // 如果没有设置密码，生成一个随机密码
            user.setPassword(passwordUtil.encode("123456")); // 默认密码，用户可以后续修改
        }
        user.setNickname(registerDTO.getNickname());
        user.setEmail(registerDTO.getEmail());
        user.setPhone(registerDTO.getPhone());
        user.setStatus(1);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        user.setDeleted(0);

        userMapper.insert(user);

        // 为新用户分配基础权限
        permissionInitService.createBasicUserPermissions(user.getId());
    }
    
    @Override
    public UserInfoVO getUserInfo(String username) {
        // 查询用户
        User user = userMapper.selectByUsername(username);

        if (user == null) {
            throw BusinessException.userNotFound(username);
        }
        
        // 查询用户角色
        List<UserRole> userRoles = userRoleMapper.selectByUserId(user.getId());
        
        List<String> roles = userRoles.stream()
                .map(ur -> {
                    Role role = roleMapper.selectById(ur.getRoleId());
                    return role != null ? role.getRoleName() : null;
                })
                .filter(roleName -> roleName != null)
                .collect(Collectors.toList());
        
        UserInfoVO userInfoVO = new UserInfoVO();
        userInfoVO.setId(user.getId());
        userInfoVO.setUsername(user.getUsername());
        userInfoVO.setNickname(user.getNickname());
        userInfoVO.setEmail(user.getEmail());
        userInfoVO.setPhone(user.getPhone());
        userInfoVO.setAvatar(user.getAvatar());
        userInfoVO.setMemberLevel(user.getMemberLevel());
        userInfoVO.setRoles(roles);
        
        // 获取用户菜单和按钮权限
        userInfoVO.setMenus(menuService.getUserMenus(user.getId()));
        userInfoVO.setButtons(menuService.getUserButtons(user.getId()));
        


        return userInfoVO;
    }



    /**
     * 生成学年格式：xxxx-xxxx
     */
    private String generateAcademicYearOnly(String grade, Integer currentYear) {
        try {
            int gradeYear = Integer.parseInt(grade);

            // 计算当前所在的学年
            int academicStartYear = gradeYear + (currentYear - 1);
            int academicEndYear = academicStartYear + 1;

            return String.format("%d-%d", academicStartYear, academicEndYear);
        } catch (Exception e) {
            return "格式错误";
        }
    }



    @Override
    public void updateProfile(String username, UpdateProfileDTO updateProfileDTO) {
        // 查询用户
        User user = userMapper.selectByUsername(username);

        if (user == null) {
            throw BusinessException.userNotFound(username);
        }

        // 更新用户信息
        user.setNickname(updateProfileDTO.getNickname());
        user.setEmail(updateProfileDTO.getEmail());
        user.setPhone(updateProfileDTO.getPhone());
        if (updateProfileDTO.getAvatar() != null) {
            user.setAvatar(updateProfileDTO.getAvatar());
        }
        user.setUpdateTime(LocalDateTime.now());

        userMapper.updateById(user);
    }
    
    @Override
    public void changePassword(String username, ChangePasswordDTO changePasswordDTO) {
        // 查询用户
        User user = userMapper.selectByUsername(username);

        if (user == null) {
            throw BusinessException.userNotFound(username);
        }

        // 验证原密码
        if (!passwordUtil.matches(changePasswordDTO.getOldPassword(), user.getPassword())) {
            throw new BusinessException(ErrorCode.USER_PASSWORD_ERROR, "原密码错误");
        }

        // 更新密码
        user.setPassword(passwordUtil.encode(changePasswordDTO.getNewPassword()));
        user.setUpdateTime(LocalDateTime.now());

        userMapper.updateById(user);
    }

    @Override
    public UserInfoVO getCurrentUserInfo() {
        String username = userContextUtil.getCurrentUsername();
        if (username == null) {
            throw new BusinessException(ErrorCode.AUTH_TOKEN_INVALID, "用户未登录或token无效");
        }

        return getUserInfo(username);
    }

    @Override
    public void updateCurrentUserProfile(UpdateProfileDTO updateProfileDTO) {
        String username = userContextUtil.getCurrentUsername();
        if (username == null) {
            throw new BusinessException(ErrorCode.AUTH_TOKEN_INVALID, "用户未登录或token无效");
        }

        updateProfile(username, updateProfileDTO);
    }

    @Override
    public void changeCurrentUserPassword(ChangePasswordDTO changePasswordDTO) {
        String username = userContextUtil.getCurrentUsername();
        if (username == null) {
            throw new BusinessException(ErrorCode.AUTH_TOKEN_INVALID, "用户未登录或token无效");
        }

        changePassword(username, changePasswordDTO);
    }

    @Override
    public TokenRefreshVO refreshToken(String refreshToken) {
        // 验证刷新token是否有效
        if (!jwtUtil.validateToken(refreshToken)) {
            throw new BusinessException(ErrorCode.AUTH_TOKEN_EXPIRED, "刷新token无效或已过期");
        }

        // 检查是否为刷新token
        if (!jwtUtil.isRefreshToken(refreshToken)) {
            throw new BusinessException(ErrorCode.AUTH_TOKEN_INVALID, "无效的刷新token类型");
        }

        // 从刷新token中获取用户名
        String username = jwtUtil.getUsernameFromToken(refreshToken);
        if (username == null || username.isEmpty()) {
            throw new BusinessException(ErrorCode.AUTH_TOKEN_INVALID, "无法从刷新token中获取用户信息");
        }

        // 验证用户是否存在且状态正常
        User user = userMapper.selectByUsername(username);
        if (user == null) {
            throw BusinessException.userNotFound(username);
        }

        if (user.getStatus() == 0) {
            throw BusinessException.userDisabled();
        }

        // 生成新的访问token和刷新token
        String newAccessToken = jwtUtil.generateToken(username);
        String newRefreshToken = jwtUtil.generateRefreshToken(username);

        TokenRefreshVO tokenRefreshVO = new TokenRefreshVO();
        tokenRefreshVO.setAccessToken(newAccessToken);
        tokenRefreshVO.setRefreshToken(newRefreshToken);
        tokenRefreshVO.setExpiresIn(7200L); // 2小时，单位：秒

        return tokenRefreshVO;
    }

    /**
     * 记录用户上线
     */
    private void recordUserOnline(String tokenId, User user) {
        try {
            OnlineUserVO onlineUser = new OnlineUserVO();
            onlineUser.setTokenId(tokenId);
            onlineUser.setUserId(user.getId());
            onlineUser.setUsername(user.getUsername());
            onlineUser.setNickname(user.getNickname());
            onlineUser.setDeptName("未分配部门"); // 可以根据实际情况获取部门信息
            onlineUser.setLoginTime(LocalDateTime.now());
            onlineUser.setLastAccessTime(LocalDateTime.now());
            onlineUser.setStatus("在线");

            // 获取请求信息
            try {
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                if (attributes != null) {
                    HttpServletRequest request = attributes.getRequest();
                    onlineUser.setIpaddr(IpUtil.getClientIpAddress(request));
                    onlineUser.setLoginLocation(IpUtil.getLocationByIp(onlineUser.getIpaddr()));

                    String userAgent = request.getHeader("User-Agent");
                    onlineUser.setBrowser(parseBrowser(userAgent));
                    onlineUser.setOs(parseOS(userAgent));
                }
            } catch (Exception e) {
                // 获取请求信息失败，使用默认值
                onlineUser.setIpaddr("未知");
                onlineUser.setLoginLocation("未知");
                onlineUser.setBrowser("未知");
                onlineUser.setOs("未知");
            }

            // 记录到Redis
            onlineUserService.userOnline(tokenId, onlineUser);

        } catch (Exception e) {
            // 记录在线用户失败不应该影响登录流程
            e.printStackTrace();
        }
    }

    /**
     * 解析浏览器类型
     */
    private String parseBrowser(String userAgent) {
        if (userAgent == null) return "未知";

        if (userAgent.contains("Chrome")) return "Chrome";
        if (userAgent.contains("Firefox")) return "Firefox";
        if (userAgent.contains("Safari")) return "Safari";
        if (userAgent.contains("Edge")) return "Edge";
        if (userAgent.contains("Opera")) return "Opera";

        return "其他";
    }

    /**
     * 解析操作系统
     */
    private String parseOS(String userAgent) {
        if (userAgent == null) return "未知";

        if (userAgent.contains("Windows NT 10")) return "Windows 10";
        if (userAgent.contains("Windows NT 6.3")) return "Windows 8.1";
        if (userAgent.contains("Windows NT 6.2")) return "Windows 8";
        if (userAgent.contains("Windows NT 6.1")) return "Windows 7";
        if (userAgent.contains("Windows")) return "Windows";
        if (userAgent.contains("Mac OS X")) return "Mac OS X";
        if (userAgent.contains("Linux")) return "Linux";
        if (userAgent.contains("Android")) return "Android";
        if (userAgent.contains("iPhone")) return "iOS";

        return "其他";
    }

    /**
     * 用户名密码登录
     */
    private User loginWithPassword(LoginDTO loginDTO) {
        if (loginDTO.getUsername() == null || loginDTO.getPassword() == null) {
            throw new BusinessException(ErrorCode.PARAMETER_ERROR, "用户名和密码不能为空");
        }

        User user = userMapper.selectByUsername(loginDTO.getUsername());
        if (user == null) {
            throw BusinessException.userNotFound(loginDTO.getUsername());
        }

        if (!passwordUtil.matches(loginDTO.getPassword(), user.getPassword())) {
            throw BusinessException.userPasswordError();
        }

        return user;
    }

    /**
     * 手机号验证码登录
     */
    private User loginWithPhone(LoginDTO loginDTO) {
        if (loginDTO.getPhone() == null || loginDTO.getCode() == null) {
            throw new BusinessException(ErrorCode.PARAMETER_ERROR, "手机号和验证码不能为空");
        }

        // 验证验证码
        Result<Void> verifyResult = phoneVerificationService.verifyLoginCode(loginDTO.getPhone(), loginDTO.getCode());
        if (!verifyResult.isSuccess()) {
            throw new BusinessException(ErrorCode.AUTH_VERIFICATION_CODE_ERROR, verifyResult.getMessage());
        }

        User user = userMapper.selectByPhone(loginDTO.getPhone());
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_FOUND, "该手机号未注册");
        }

        return user;
    }

    /**
     * 邮箱验证码登录
     */
    private User loginWithEmail(LoginDTO loginDTO) {
        if (loginDTO.getUsername() == null || loginDTO.getCode() == null) {
            throw new BusinessException(ErrorCode.PARAMETER_ERROR, "邮箱和验证码不能为空");
        }

        // 验证验证码
        Result<Void> verifyResult = emailVerificationService.verifyLoginCode(loginDTO.getUsername(), loginDTO.getCode());
        if (!verifyResult.isSuccess()) {
            throw new BusinessException(ErrorCode.AUTH_VERIFICATION_CODE_ERROR, verifyResult.getMessage());
        }

        User user = userMapper.selectByEmail(loginDTO.getUsername());
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_FOUND, "该邮箱未注册");
        }

        return user;
    }
}